//大文件分片上传,比如10G的压缩包,或者视频等,这些文件太大了  (需要后端配合进行)
class FileSliceUpload {

    constructor(testingUrl, uploadUrl, margeUrl, fileSelect) {
        this.testingUrl = testingUrl; // 检测文件上传的url
        this.uploadUrl = uploadUrl;//文件上传接口
        this.margeUrl = margeUrl; // 合并文件接口
        this.fileSelect = fileSelect;
        this.fileObj = null;
        this.totalsize = null;
        this.blockSize = 1024 * 1024; //每次上传多少字节1mb(最佳)
        this.sta = 0; //起始位置
        this.end = this.sta + this.blockSize; //结束位置
        this.count = 0; //分片个数
        this.barId = "bar"; //进度条id
        this.progressId = "progress";//进度数值ID
        this.progressNow = 0;
        this.progressTotal = 0;
        this.fileSliceName = ""; //分片文件名称
        this.fileName = "";
        this.uploadFileInterval = null;  //上传文件定时器

    }

    /**
     *  样式可以进行修改
     * @param {*} progressId   需要将进度条添加到那个元素下面
     */
    addProgress(progressSelect) {
        let bar = document.createElement("div")
        bar.setAttribute("id", this.barId);
        let num = document.createElement("div")
        num.setAttribute("id", this.progressId);
        num.innerText = "0%"
        bar.appendChild(num);
        document.querySelector(progressSelect).appendChild(bar)

    }

    //续传  在上传前先去服务器检测之前是否有上传过这个文件,如果还有返回上传的的分片,那么进行续传
    // 将当前服务器上传的最后一个分片会从新上传, 避免因为网络的原因导致分片损坏
    sequelFile() {
        if (this.fileName) {
            var xhr = new XMLHttpRequest();
            //同步
            var url = this.testingUrl + "/" + this.fileName + "/" + this.blockSize + "/" + this.totalsize;
            xhr.open('GET', encodeURI(url), false);
            xhr.send();
            if (xhr.readyState === 4 && xhr.status === 200) {
                let ret = JSON.parse(xhr.response)
                if (ret.code == 0) {
                    let data = ret.data
                    this.count = data.code;
                    this.fileSliceName = data.fileSliceName
                    //计算起始位置和结束位置
                    this.sta = this.blockSize * this.count
                    //计算结束位置
                    this.end = this.sta + this.blockSize
                    this.progressNow = data.progressNow
                } else {
                    this.sta = 0; //从头开始
                    this.end = this.sta + this.blockSize;
                    this.count = 0; //分片个数
                    this.progressNow = 0;
                }
            }
        }
    }

    stopUploadFile() {
        console.log("stop!!!")
        clearInterval(this.uploadFileInterval)
    }

    // 文件上传(单文件)
    startUploadFile() {
        this.resetProgress();

        this.fileObj = document.querySelector(this.fileSelect).files[0];
        this.totalsize = this.fileObj.size;
        this.fileName = this.fileObj.name;
        this.progressTotal = Math.ceil(this.totalsize / this.blockSize)
        console.log("文件总大小：" + this.totalsize + ", 需要分片个数： " + this.progressTotal )

        //查询是否存在之前上传过此文件,然后继续
        this.sequelFile()
        let ref = this; //拿到当前对象的引用,因为是在异步中使用this就是他本身而不是class
        this.uploadFileInterval = setInterval(function () {
            if (ref.sta > ref.totalsize) {
                //上传完毕后结束定时器
                clearInterval(ref.uploadFileInterval)
                //发送合并请求
                ref.margeUploadFile()
                console.log("stop" + ref.sta);
                return;
            }
            ;
            //分片名称
            ref.fileSliceName = ref.fileName + "-slice-" + ref.count++
            //分割文件 ,
            var blob1 = ref.fileObj.slice(ref.sta, ref.end);
            console.log("start: "+ ref.sta + ", end : "+ ref.end)
            var fd = new FormData();
            fd.append('part', blob1);
            fd.append('fileSliceName', ref.fileSliceName);
            fd.append('fileSize', ref.totalsize);
            var xhr = new XMLHttpRequest();
            xhr.open('POST', ref.uploadUrl, true);
            xhr.send(fd); //异步发送文件,不管是否成功, 会定期检测

            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    let ret = JSON.parse(xhr.response)
                    if (ret.code == 0) {
                        console.log(ret.data);
                        ref.progressNow++;
                        ref.calculateProgress();
                    }
                }
            }
            //起始位置等于上次上传的结束位置
            ref.sta = ref.end;
            //结束位置等于上次上传的结束位置+每次上传的字节
            ref.end = ref.sta + ref.blockSize;
        }, 100)

    }

    margeUploadFile() {
        console.log("检测上传的文件完整性..........");
        var xhr = new XMLHttpRequest();
        //文件分片的名称/分片大小/总大小
        var url = this.margeUrl + "/" + this.fileSliceName + "/" + this.blockSize + "/" + this.totalsize;
        xhr.open('GET', encodeURI(url), true);
        xhr.send(); //发送请求
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                let ret = JSON.parse(xhr.response)
                if (ret.code == 0) {
                    console.log("文件上传完毕");
                    let address = document.getElementById("address");
                    address.value = ret.msg;
                    address.style.display = "block"
                } else {
                    console.log("上传完毕但是文件上传过程中出现了异常", ret);
                }
            }
        }

    }

    calculateProgress() {
        let bar = document.getElementById(this.barId)
        let progressEl = document.getElementById(this.progressId)
        let percent = Math.ceil((this.progressNow / this.progressTotal) * 100)
        if (percent > 100) {
            percent = 100
        }
        bar.style.width = percent + '%';
        bar.style.backgroundColor = 'green';
        progressEl.innerHTML = percent + '%'
    }

    resetProgress(){
        let bar = document.getElementById(this.barId)
        let progressEl = document.getElementById(this.progressId)
        bar.style.width = 0 + '%';
        bar.style.backgroundColor = 'green';
        progressEl.innerHTML = 0 + '%'
    }

}


